package org.hawk.gwt.ppc.introspection.impl;

import java.util.List;

import org.hawk.gwt.ppc.introspection.JavaModifier;
import org.hawk.gwt.ppc.introspection.JavaTypeScope;
import org.hawk.gwt.ppc.introspection.JavaVariable;
import org.hawk.gwt.ppc.parser.ModificatedDescriptor;
import org.hawk.gwt.ppc.parser.VariableDescriptor;
import org.hawk.gwt.ppc.utils.Name;

/**
 * Implementation of introspection {@link JavaVariable} interface.
 * 
 * @author alex.bereznevatiy@gmail.com
 *
 */
class JavaVariableImpl extends AbstractJavaStatement implements JavaVariable {
	
	private String name;
	private String typeName;
	private JavaTypeScope type;
	private JavaScopeImpl scope;
	private VariableDescriptor descriptor;

	JavaVariableImpl(VariableDescriptor descriptor, JavaScopeImpl scope) {
		super();
		this.scope = scope;
		scope.getCompilationUnit();
		if (descriptor != null) {
			this.name = descriptor.getName();
			this.typeName = descriptor.getType();
			this.descriptor = descriptor;
			this.setModifiers(descriptor);
		}
	}

	List<JavaModifier> setModifiers(ModificatedDescriptor descriptor) {
		List<JavaModifier> result = fromStrings(descriptor.getModifiers());
		setModifiers(result);
		return result;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaVariable#getName()
	 */
	public String getName() {
		return name;
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaVariable#getTypeName()
	 */
	public String getTypeName() {
		if (type == null) {
			type = resolveType();
		}
		if (typeName == null) {
			return type.getName();
		}
		return type.getName() + Name.getTypeParameters(typeName);
	}

	JavaTypeScope resolveType() {
		return GenericHelper.buildGenericType(typeName, scope);
	}

	/*
	 * (non-Javadoc)
	 * @see org.hawk.gwt.ppc.introspection.JavaVariable#getTypeDescriptor()
	 */
	public JavaTypeScope getTypeDescriptor() {
		if (type == null) {
			type = resolveType();
		}
		return type;
	}

	/**
	 * @return descriptor that represents this variable in the AST.
	 */
	VariableDescriptor getDescriptor() {
		return descriptor;
	}
	
	/**
	 * @return scope this variable belongs to.
	 */
	JavaScopeImpl getScope() {
		return scope;
	}
}
